(define (z1 mtx)
; находим список пар (строка . кол-во нулей)
  (if (empty? mtx)
      #f
      (let ( (pairs (map (λ (x y) (cons y (foldl (λ (num res) (if (= num 0) (+ res 1) res)) 0 x))) mtx mtx)))
        (let ( (result (foldl (λ (pair str)
                                (if (> (cdr pair) (cdr str)) ; сравниваем количественное значение нулей в строках
                                    pair
                                    str))
                              (car pairs) (cdr pairs))) )
          (if (= (cdr result) 0) ; если все-таки надо вернуть строку, убери эту, следущую и строку после result
              #f
              (car result)
          )
))))

; Второй вариант 
(define (problem1 matrix)
  (define answer (foldl (λ ( a result )
                          (if (<= (cdr result) (apply + (map (λ (x) (if (= x 0) 1 0)) a)))
                              (cons a (apply + (map (λ (x) (if (= x 0) 1 0)) a)))
                              result
                )) '(0 . 0) matrix ))
  (car answer))

;------------------------------------------------------------

(define (z2 n)
  (build-list n (λ (i) (build-list n (λ (j)                                    ; i, j - индексы строки и стобцов
                          (if (< i (/ n 2))                                    ; 
                              (if (and (> j i) (< j (- (- n 1) i))) 0 1)       ; если индексы элемента[i,j] находятся над диагоналями - 0, нет - 1
                              (if (and (> j (- (- n 1) i)) (< j i)) 0 1))))))) ; если индексы элемента[i,j] находятся под диагоналями - 0, нет - 1

; Второй вариант
(define (problem2 n)
  (define upper-part (build-list (quotient n 2) (λ (column)
                                                  (build-list n (λ (row) (if (and (> row column) (< row (- n 1 column))) 0 1 ))))))
  (if (even? n)
      (append upper-part (reverse upper-part))
      (append upper-part (list (make-list n 1)) (reverse upper-part))))                            
                            
;------------------------------------------------------------
(define (z3 mtx)
  (if (empty? mtx)
      #f
      (let ( (saddle-points (foldl (λ (str res)                                                                   ; пробегаемся по строкам изначальной матрицы
                                     (foldl (λ (element x res)                                                    ; пробегаемся по элементам строки и индексам
                                              (if (and (= element (apply min str))                                ; если элемент минимальный из строки
                                                       (= element (apply max (list-ref (apply map list mtx) x)))) ;   и максимальный из стоблца 
                                                  (cons element res)                                              ; добавляем к результату
                                                  res                                                             ; пропускаем элемент
                                                  )
                                              ) res str (build-list (length str) +))                              ; передаем результирующий список, строку и список индексов
                                     ) '() mtx )))                                                                ; res = '(), str - строки из mtx
        (if (empty? saddle-points)  ; если седловых точек нет
            #f
            saddle-points
            ))))

; Второй вариант                            
(define (min_ lst) (foldl (λ (x res) (if (< x res) x res)) (car lst) (cdr lst))) ; минимальное число из списка
(define (max_ lst) (foldl (λ (x res) (if (> x res) x res)) (car lst) (cdr lst))) ; максимальное число из списка
(define (tran-mtx matrix) (apply map list matrix))                               ; транспрнирование матрицы

(define (problem3 matrix)
  (foldl (λ ( row result )
           (foldl (λ ( column element result ) (if ( = element (min_ row) (max_ column))     ; если элемент минимальный в строке и максимальный в столбце
                                                   (cons element result)                     ; добавляем 
                                                   result
                                              )) result (tran-mtx matrix) row)) '() matrix))                            
                            
;------------------------------------------------------------
(define (z4 mtx)
  (define index (build-list (length mtx) (λ (x) x))) ; создаем список индексов от 0 .. n-1
  (define (diag-sum mtx)
    (foldl (λ (str i sum) (+ sum (list-ref str i))) 0 mtx index)) ; находим сумму диагонали
; находим суммы диагонали первой матрицы и диагонали второй матрицы
  (let ( (sum1 (diag-sum mtx)) (sum2 (diag-sum (reverse mtx))))
    (andmap (λ (x y) (= (apply + x) (apply + y) sum1 sum2)) mtx (apply map list mtx))))

  
; Второй вариант                                    
(define (sum_ lst) (foldl (λ (x res) (+ x res)) 0 lst)) ; сумма списка

(define (problem4 matrix)
  (define main-diag (map (λ (i row) (list-ref row i)) (build-list (length matrix) + ) matrix))                    ; список элементов главной диагонали
  (define side-diag (map (λ (i row) (list-ref row (- (length row) 1 i))) (build-list (length matrix) + ) matrix)) ; список элементов побочной диагонали
  (if (and (= (sum_ main-diag) (sum_ side-diag)) (not (empty? matrix)))                                           ; если суммы диагоналей равны и список непуст
      (foldl (λ (row column result) (= (sum_ main-diag) (sum_ row))) #t matrix (tran-mtx matrix))                 ; проверяем все строки и столбцы на равенство
      #f
))                                     

;------------------------------------------------------------
(define (z5 mtx)
  (define tran_mtx (apply map list mtx))
  (foldl (λ (str1 res)                     ; пробегаемся по всем строкам первой матрицы
           (foldl (λ (str2 res)            ; пробегаемся по всем строкам второй матрицы и сравниваем с текущей строкой из первой
                    (if (equal? str1 str2) ; если строка равна какому-то стоблцу, то перезаписываем результат этой строкой, иначе сохраняем res
                        str1
                        res
                        )
                    ) res tran_mtx)
           ) #f mtx)) 

; Второй вариант                                     
(define (problem5 matrix)
  (define transposed (tran-mtx matrix)) ; транспонируем матрицу
  (foldl (λ (row result) (if (ormap (λ (column) (equal? column row)) transposed) row result)) #f matrix)) ; каждую строку из матрицы проверяем на вхождение в мн-во столбцов
                                     